using System;
using System.IO;
using System.Net;
using System.Text;
using Newtonsoft.Json;

namespace HarrisDesigns.Controls.dasBlogControls
{
    public abstract class JsonRepository<T> : IJsonRepository<T>
    {
        private int _pollingInterval = 5;

        #region IJsonRepository<T> Members

        public string UserIdentity { get; set; }

        public int PollingInterval
        {
            get { return _pollingInterval; }
            set { _pollingInterval = value; }
        }

        public abstract DataStore<T> DataStore { get; }

        public void LoadDataFromSource(int timeout, bool isSyncronous)
        {
            if (timeout < 1000)
                throw new ArgumentException("Cannot realistically retrieve json data within less than one second",
                                            "timeout");
            var request =
                (HttpWebRequest)
                WebRequest.Create(GetJsonRequestUrl());
            request.Method = "GET";
            request.Timeout = timeout;
            if (isSyncronous)
                DeserializeToData((HttpWebResponse) request.GetResponse());
            else
                request.BeginGetResponse(LoadDataFromAsyncResult, request);
        }

        public T GetCurrentData()
        {
            if (PollingInterval < 1) throw new ArgumentException("Cannot poll more often than every 1 minute");

            if (IsDataMissing) LoadDataFromSource(3000, true);
            if (IsDataStale) LoadDataFromSource(25000, false);

            return DataStore.Data;
        }

        public abstract string GetJsonRequestUrl();

        public bool IsDataStale
        {
            get { return DataStore.LastUpdate.AddMinutes(PollingInterval) < DateTime.Now; }
        }

        public bool IsDataMissing
        {
            get { return DataStore.IsDataMissing; }
        }

        public void LoadDataFromAsyncResult(IAsyncResult ar)
        {
            var request = (HttpWebRequest) ar.AsyncState;
            DeserializeToData((HttpWebResponse) request.EndGetResponse(ar));
        }

        public void DeserializeToData(HttpWebResponse jsonResponse)
        {
            var responseStream = new StreamReader(jsonResponse.GetResponseStream(), Encoding.UTF8);
            var jsonData = new StringReader(responseStream.ReadToEnd());
            jsonResponse.Close();
            responseStream.Close();

            var jsonSerializer = new JsonSerializer
                                     {
                                         MissingMemberHandling = MissingMemberHandling.Ignore
                                     };
            DataStore.UpdateData((T) jsonSerializer.Deserialize(jsonData, typeof (T)));
        }

        #endregion
    }
}